home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / dalla rivista / host contacted / jikes.lha / jikes-1.11 / src / parser.cpp < prev    next >
C/C++ Source or Header  |  2000-01-07  |  24KB  |  786 lines

  1. // $Id: parser.cpp,v 1.6 2000/01/07 00:25:53 lord Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10. #include "config.h"
  11. #include <assert.h>
  12. #include <iostream.h>
  13. #include "parser.h"
  14. #include "ast.h"
  15.  
  16. void Parser::ReallocateStacks()
  17. {
  18.     int old_stack_length = stack_length;
  19.  
  20.     stack_length += STACK_INCREMENT;
  21.  
  22.     assert(stack_length <= SHRT_MAX);
  23.  
  24.     int *old_stack = stack;
  25.     stack = (int *) memmove(new int[stack_length], stack, old_stack_length * sizeof(int));
  26.     delete [] old_stack;
  27.  
  28.     Location *old_location_stack = location_stack;
  29.     location_stack = (Location *) memmove(new Location[stack_length], location_stack, old_stack_length * sizeof(Location));
  30.     delete [] old_location_stack;
  31.  
  32.     Ast **old_parse_stack = parse_stack;
  33.     parse_stack = (Ast **) memmove(new Ast *[stack_length], parse_stack, old_stack_length * sizeof(Ast *));
  34.     delete [] old_parse_stack;
  35.     parse_stack[old_stack_length] = NULL; // the first time through, we initialize parse_stack[0] to NULL !!!
  36.  
  37.     int *old_temp_stack = temp_stack;
  38.     temp_stack = (int *) memmove(new int[stack_length], temp_stack, old_stack_length * sizeof(int));
  39.     delete [] old_temp_stack;
  40.  
  41.     return;
  42. }
  43.  
  44.  
  45. AstListNode *Parser::AllocateListNode()
  46. {
  47.     AstListNode *p;
  48.  
  49.     if (free_list_nodes)
  50.     {
  51.         p = free_list_nodes;
  52.         free_list_nodes = free_list_nodes -> next;
  53.     }
  54.     else p = list_node_pool -> NewListNode();
  55.  
  56.     return p;
  57. }
  58.  
  59.  
  60. void Parser::FreeCircularList(AstListNode *tail)
  61. {
  62.     AstListNode *root = tail -> next;
  63.     tail -> next = free_list_nodes;
  64.     free_list_nodes = root;
  65.  
  66.     return;
  67. }
  68.  
  69.  
  70. AstPackageDeclaration *Parser::PackageHeaderParse(LexStream *lex_stream_, StoragePool *ast_pool_)
  71. {
  72.     AstPackageDeclaration *package_declaration = NULL;
  73.  
  74.     lex_stream_ -> Reset();
  75.  
  76.     if (lex_stream_ -> Kind(lex_stream_ -> Peek()) == TK_package)
  77.     {
  78.         ast_pool = ast_pool_;
  79.  
  80.         parse_package_header_only = true;
  81.         end_token = LexStream::LEX_INFINITY; // We are parsing the whole input and not just a segment.
  82.         lex_stream = lex_stream_;
  83.         Ast *ast = HeaderParse();
  84.         parse_package_header_only = false;
  85.  
  86.         if (ast)
  87.         {
  88.             AstCompilationUnit *compilation_unit = ast -> CompilationUnitCast();
  89.             if (compilation_unit && (! compilation_unit -> BadCompilationUnitCast()))
  90.                 package_declaration = compilation_unit -> package_declaration_opt;
  91.         }
  92.     }
  93.  
  94.     return package_declaration;
  95. }
  96.  
  97.  
  98. AstCompilationUnit *Parser::HeaderParse(LexStream *lex_stream_, StoragePool *ast_pool_)
  99. {
  100.     lex_stream_ -> Reset();
  101.  
  102.     body_pool = new StoragePool(lex_stream_ -> NumTokens());
  103.     ast_pool = (ast_pool_ ? ast_pool_ : body_pool);
  104.     list_node_pool = new StoragePool(lex_stream_ -> NumTokens());
  105.     free_list_nodes = NULL;
  106.     AstCompilationUnit *compilation_unit = NULL;
  107.  
  108.     parse_header_only = true;
  109.     end_token = LexStream::LEX_INFINITY; // We are parsing the whole input and not just a segment.
  110.     lex_stream = lex_stream_;
  111.     Ast *ast = HeaderParse();
  112.     parse_header_only = false;
  113.  
  114.     if (ast)
  115.     {
  116.         compilation_unit = ast -> CompilationUnitCast();
  117.         if (compilation_unit && (! compilation_unit -> BadCompilationUnitCast()))
  118.         {
  119.             if (compilation_unit -> NumTypeDeclarations() == 0)
  120.                 compilation_unit -> kind = Ast::EMPTY_COMPILATION;
  121.         }
  122. // STG:
  123. //      else delete ast;
  124. //
  125.     }
  126.  
  127.     //
  128.     // If we succesfully parsed a compilation unit, allocate a storage pool for it.
  129.     // Subtract the amount of space that's already been allocated for the headers
  130.     // from the estimate for the bodies.
  131.     //
  132.     if (compilation_unit)
  133.          compilation_unit -> ast_pool = body_pool;
  134.     else delete body_pool;
  135.  
  136.     delete list_node_pool; // free the pool of list nodes
  137.  
  138.     return compilation_unit;
  139. }
  140.  
  141.  
  142. Ast *Parser::HeaderParse()
  143. {
  144.     TokenObject curtok = lex_stream -> Gettoken();
  145.     int act = START_STATE,
  146.               current_kind = lex_stream -> Kind(curtok);
  147.  
  148. /*****************************************************************/
  149. /* Start parsing.                                                */
  150. /*****************************************************************/
  151.     state_stack_top = -1;
  152.  
  153.     //
  154.     // Process a terminal
  155.     //
  156.     for (;;)
  157.     {
  158.         if (++state_stack_top >= stack_length)
  159.             ReallocateStacks();
  160.  
  161.         stack[state_stack_top] = act;
  162.         location_stack[state_stack_top] = Loc(curtok);
  163.  
  164.         act = t_action(act, current_kind, lex_stream);
  165.  
  166.         if (act <= NUM_RULES)
  167.             state_stack_top--; // make reduction look like a shift-reduce
  168.         else if (act > ERROR_ACTION)
  169.         {
  170. // STG:
  171. //            token_action(curtok);
  172.             curtok = lex_stream -> Gettoken();
  173.             current_kind = lex_stream -> Kind(curtok);
  174.  
  175.             act -= ERROR_ACTION;
  176.         }
  177.         else if (act < ACCEPT_ACTION)
  178.         {
  179. // STG:
  180. //            token_action(curtok);
  181.             curtok = lex_stream -> Gettoken();
  182.             current_kind = lex_stream -> Kind(curtok);
  183.  
  184.             continue;
  185.         }
  186.         else break;
  187.  
  188.         //
  189.         // Process a non_terminal
  190.         //
  191.         do
  192.         {
  193.             state_stack_top -= (rhs[act] - 1);
  194.             (this ->* rule_action[act])();
  195.             act = nt_action(stack[state_stack_top], lhs[act]);
  196.         } while(act <= NUM_RULES);
  197.     } /* process_terminal */
  198.  
  199.     if (act == ERROR_ACTION)
  200.     {
  201.         //
  202.         // If any error is found in a package declaration, do not try to repair it.
  203.         //
  204.         if (! parse_package_header_only)
  205.             RepairParse(curtok);
  206.  
  207.         if (parse_stack[0] && parse_stack[0] -> CompilationUnitCast())
  208.             parse_stack[0] -> kind = Ast::BAD_COMPILATION;
  209.         else
  210.         {
  211. // STG:
  212. //            delete parse_stack[0];
  213.             parse_stack[0] = NULL;
  214.         }
  215.     }
  216.  
  217.     return parse_stack[0];
  218. }
  219.  
  220.  
  221. bool Parser::BodyParse(LexStream *lex_stream_, AstClassBody *class_body)
  222. {
  223.     assert(class_body -> UnparsedClassBodyCast());
  224.  
  225.     lex_stream = lex_stream_;
  226.     ast_pool = class_body -> pool;
  227.     body_pool = class_body -> pool;
  228.     list_node_pool = new StoragePool(lex_stream_ -> NumTokens());
  229.     free_list_nodes = NULL;
  230.  
  231.     bool no_errors_detected = Body(class_body);
  232.  
  233.     delete list_node_pool; // free the pool of list nodes
  234.  
  235.     class_body -> mark_parsed();
  236.  
  237.     return no_errors_detected;
  238. }
  239.  
  240.  
  241. bool Parser::Body(AstClassBody *class_body)
  242. {
  243.     bool no_errors_detected = true;
  244.  
  245.     for (int i = 0; i < class_body -> NumConstructors(); i++)
  246.     {
  247.         AstConstructorDeclaration *constructor_decl = class_body -> Constructor(i);
  248.  
  249.         if (constructor_decl -> constructor_symbol)
  250.         {
  251.             AstConstructorBlock *block = constructor_decl -> constructor_body;
  252.             end_token = block -> right_brace_token; // last token in the body
  253.  
  254.             AstStatement *new_body = (AstStatement *) ParseSegment(block -> left_brace_token);
  255.  
  256.             if (! new_body)
  257.                 no_errors_detected = false;
  258.             else
  259.             {
  260.                 AstConstructorBlock *new_block = new_body -> ConstructorBlockCast();
  261.  
  262.                 if (! new_block)
  263.                 {
  264.                     new_block                                        = ast_pool -> GenConstructorBlock();
  265.                     new_block -> left_brace_token                    = new_body -> LeftToken();
  266.                     new_block -> explicit_constructor_invocation_opt = NULL;
  267.                     new_block -> block                               = (AstBlock *) new_body;
  268.                     new_block -> right_brace_token                   = new_body -> RightToken();
  269.                 }
  270. // STG:
  271. //                delete block; // destroy old empty block
  272. //
  273.                 constructor_decl -> constructor_body = new_block;
  274.             }
  275.         }
  276.     }
  277.  
  278.     for (int j = 0; j < class_body -> NumMethods(); j++)
  279.     {
  280.         AstMethodDeclaration *method_decl = class_body -> Method(j);
  281.  
  282.         if (method_decl -> method_symbol)
  283.         {
  284.             AstBlock *block = method_decl -> method_body -> BlockCast();
  285.  
  286.             if (block)
  287.             {
  288.                 end_token = block -> right_brace_token; // last token in the body
  289.                 AstStatement *new_block = (AstStatement *) ParseSegment(block -> left_brace_token);
  290.  
  291.                 if (! new_block) // a bad block ?
  292.                     no_errors_detected = false;
  293.                 else
  294.                 {
  295.                     //
  296.                     // The block associated with the method may syntactically be either a
  297.                     // block or a constructor block. If it is a block, nest it inside the
  298.                     // initial block. If it is a constructor block, replace the initial block
  299.                     // by the constructor block.
  300.                     //
  301.                     if (new_block -> BlockCast())
  302.                         block -> AddStatement(new_block);
  303.                     else
  304.                     {
  305.                         method_decl -> method_body = new_block;
  306. // STG:
  307. //                        delete block; // destroy old empty block
  308.                     }
  309.                 }
  310.             }
  311.         }
  312.     }
  313.  
  314.     for (int k = 0; k < class_body -> NumNestedClasses(); k++)
  315.         no_errors_detected = no_errors_detected && Body(class_body -> NestedClass(k) -> class_body);
  316.  
  317.     for (int l = 0; l < class_body -> NumNestedInterfaces(); l++)
  318.         no_errors_detected = no_errors_detected && Body(class_body -> NestedInterface(l));
  319.  
  320.     return no_errors_detected;
  321. }
  322.  
  323. bool Parser::BodyParse(LexStream *lex_stream_, AstInterfaceDeclaration *interface_declaration)
  324. {
  325.     assert(interface_declaration -> UnparsedInterfaceBodyCast());
  326.  
  327.     lex_stream = lex_stream_;
  328.     ast_pool = interface_declaration -> pool;
  329.     body_pool = interface_declaration -> pool;
  330.     list_node_pool = new StoragePool(lex_stream_ -> NumTokens());
  331.     free_list_nodes = NULL;
  332.  
  333.     bool no_errors_detected = Body(interface_declaration);
  334.  
  335.     delete list_node_pool; // free the pool of list nodes
  336.  
  337.     interface_declaration -> mark_parsed();
  338.  
  339.     return no_errors_detected;
  340. }
  341.  
  342.  
  343. bool Parser::Body(AstInterfaceDeclaration *interface_declaration)
  344. {
  345.     bool no_errors_detected = true;
  346.  
  347.     for (int k = 0; k < interface_declaration -> NumNestedClasses(); k++)
  348.         no_errors_detected = no_errors_detected && Body(interface_declaration -> NestedClass(k) -> class_body);
  349.  
  350.     for (int l = 0; l < interface_declaration -> NumNestedInterfaces(); l++)
  351.         no_errors_detected = no_errors_detected && Body(interface_declaration -> NestedInterface(l));
  352.  
  353.     return no_errors_detected;
  354. }
  355.  
  356.  
  357. bool Parser::InitializerParse(LexStream *lex_stream_, AstClassBody *class_body)
  358. {
  359.     lex_stream = lex_stream_;
  360.     ast_pool = class_body -> pool;
  361.     body_pool = class_body -> pool;
  362.     list_node_pool = new StoragePool(lex_stream_ -> NumTokens());
  363.     free_list_nodes = NULL;
  364.  
  365.     bool no_errors_detected = Initializer(class_body);
  366.  
  367.     delete list_node_pool; // free the pool of list nodes
  368.  
  369.     return no_errors_detected;
  370. }
  371.  
  372.  
  373. bool Parser::InitializerParse(LexStream *lex_stream_, AstInterfaceDeclaration *interface_declaration)
  374. {
  375.     lex_stream = lex_stream_;
  376.     ast_pool = interface_declaration -> pool;
  377.     body_pool = interface_declaration -> pool;
  378.     list_node_pool = new StoragePool(lex_stream_ -> NumTokens());
  379.     free_list_nodes = NULL;
  380.  
  381.     bool no_errors_detected = Initializer(interface_declaration);
  382.  
  383.     delete list_node_pool; // free the pool of list nodes
  384.  
  385.     return no_errors_detected;
  386. }
  387.  
  388.  
  389. bool Parser::Initializer(AstClassBody *class_body)
  390. {
  391.     bool no_errors_detected = true;
  392.  
  393.     for (int i = 0; i < class_body -> NumStaticInitializers(); i++)
  394.     {
  395.          AstBlock *block = class_body -> StaticInitializer(i) -> block;
  396.          end_token = block -> right_brace_token; // last token in the body
  397.          class_body -> StaticInitializer(i) -> block = (AstBlock *) ParseSegment(block -> left_brace_token);
  398.  
  399.         if (! class_body -> StaticInitializer(i) -> block)
  400.         {
  401.             no_errors_detected = false;
  402.             class_body -> StaticInitializer(i) -> block = block; // restore old empty block
  403.         }
  404. // STG:
  405. //      else
  406. //      {
  407. //          delete block; // destroy old empty block
  408. //      }
  409.     }
  410.  
  411.     for (int j = 0; j < class_body -> NumBlocks(); j++)
  412.     {
  413.          AstBlock *block = class_body -> Block(j);
  414.          end_token = block -> right_brace_token; // last token in the body
  415.          class_body -> Block(j) = (AstBlock *) ParseSegment(block -> left_brace_token);
  416.  
  417.         if (! class_body -> Block(j))
  418.         {
  419.             no_errors_detected = false;
  420.             class_body -> Block(j) = block; // restore old empty block
  421.         }
  422. //
  423. // STG: if we ever go back to a new/free model of allocating Ast nodes
  424. // This loop needs to be rewritten as otherwise, the new block allocated
  425. // here would cause a memory leak since the class_body_declarations list
  426. // is unaware of it. The solution is to iterate over the class_body_declarations
  427. // list in order to locate the old block, free it and update the class_body_declarations
  428. // list to point to the new block.
  429. //
  430.     }
  431.  
  432.     for (int k = 0; k < class_body -> NumNestedClasses(); k++)
  433.         no_errors_detected = no_errors_detected && Initializer(class_body -> NestedClass(k) -> class_body);
  434.  
  435.     for (int l = 0; l < class_body -> NumNestedInterfaces(); l++)
  436.         no_errors_detected = no_errors_detected && Initializer(class_body -> NestedInterface(l));
  437.  
  438.     return no_errors_detected;
  439. }
  440.  
  441.  
  442. bool Parser::Initializer(AstInterfaceDeclaration *interface_declaration)
  443. {
  444.     bool no_errors_detected = true;
  445.  
  446.     for (int k = 0; k < interface_declaration -> NumNestedClasses(); k++)
  447.         no_errors_detected = no_errors_detected && Initializer(interface_declaration -> NestedClass(k) -> class_body);
  448.  
  449.     for (int l = 0; l < interface_declaration -> NumNestedInterfaces(); l++)
  450.         no_errors_detected = no_errors_detected && Initializer(interface_declaration -> NestedInterface(l));
  451.  
  452.     return no_errors_detected;
  453. }
  454.  
  455.  
  456. Ast *Parser::ParseSegment(TokenObject start_token)
  457. {
  458.     //
  459.     // The next call to Gettoken will return the start_token.
  460.     // However, we initialize curtok to start_token in order
  461.     // to obtain a valid location for the BodyMarker.
  462.     //
  463.     lex_stream -> Reset(start_token);
  464.     TokenObject curtok = start_token; // get the location of the start_token
  465.     int act = START_STATE,
  466.               current_kind = TK_BodyMarker;
  467.  
  468. /*****************************************************************/
  469. /* Start parsing.                                                */
  470. /*****************************************************************/
  471.     state_stack_top = -1;
  472.  
  473.     //
  474.     // Process a terminal
  475.     //
  476.     for (;;)
  477.     {
  478.         if (++state_stack_top >= stack_length)
  479.             ReallocateStacks();
  480.  
  481.         stack[state_stack_top] = act;
  482.         location_stack[state_stack_top] = Loc(curtok);
  483.  
  484.         act = t_action(act, current_kind, lex_stream);
  485.  
  486.         if (act <= NUM_RULES)
  487.             state_stack_top--; // make reduction look like a shift-reduce
  488.         else if (act > ERROR_ACTION)
  489.         {
  490. // STG:
  491. //            token_action(curtok);
  492.             curtok = lex_stream -> Gettoken(end_token);
  493.             current_kind = lex_stream -> Kind(curtok);
  494.  
  495.             act -= ERROR_ACTION;
  496.         }
  497.         else if (act < ACCEPT_ACTION)
  498.         {
  499. // STG:
  500. //            token_action(curtok);
  501.             curtok = lex_stream -> Gettoken(end_token);
  502.             current_kind = lex_stream -> Kind(curtok);
  503.  
  504.             continue;
  505.         }
  506.         else break;
  507.  
  508.         //
  509.         // Process a nonterminal
  510.         //
  511.         do
  512.         {
  513.             state_stack_top -= (rhs[act] - 1);
  514.             (this ->* rule_action[act])();
  515.             act = nt_action(stack[state_stack_top], lhs[act]);
  516.         } while(act <= NUM_RULES);
  517.     } /* process_terminal */
  518.  
  519.     if (act == ERROR_ACTION)
  520.     {
  521.         RepairParse(curtok);
  522.  
  523. // STG:
  524. //        delete parse_stack[0];
  525.         parse_stack[0] = NULL;
  526.     }
  527.  
  528.     return parse_stack[0];
  529. }
  530.  
  531.  
  532. void Parser::RepairParse(TokenObject curtok)
  533. {
  534.     //
  535.     // Repair an error
  536.     //
  537.     for (;;)
  538.     {
  539.         //
  540.         // Pop state stack up to first state that had an
  541.         // action on the error token.  The net effect is to
  542.         // remove all default reductions on an empty rule
  543.         // caused by the error token.
  544.         //
  545.         int k;
  546.         for (k = state_stack_top - 1; k >= 0 && location_stack[k] == Loc(curtok); k--)
  547.              ;
  548.         k++;
  549. // STG:
  550. //        for (int i = k; i < state_stack_top; i++)
  551. //        {
  552. //            delete parse_stack[i];
  553. //        }
  554.  
  555.         state_stack_top = k;
  556.  
  557.         ErrorRepair(curtok);
  558.  
  559.         curtok = lex_stream -> Gettoken(end_token);
  560.         int act = stack[state_stack_top--];
  561.         int current_kind = lex_stream -> Kind(curtok);
  562.  
  563.         //
  564.         // Process a terminal
  565.         //
  566.         for (;;)
  567.         {
  568.             if (++state_stack_top >= stack_length)
  569.                  ReallocateStacks();
  570.  
  571.             stack[state_stack_top] = act;
  572.             location_stack[state_stack_top] = Loc(curtok);
  573.  
  574.             act = t_action(act, current_kind, lex_stream);
  575.  
  576.             if (act <= NUM_RULES)
  577.                 state_stack_top--; // make reduction look like a shift-reduce
  578.             else if (act > ERROR_ACTION)
  579.             {
  580. // STG:
  581. //                token_action(curtok);
  582.                 curtok = lex_stream -> Gettoken(end_token);
  583.                 current_kind = lex_stream -> Kind(curtok);
  584.  
  585.                 act -= ERROR_ACTION;
  586.             }
  587.             else if (act < ACCEPT_ACTION)
  588.             {
  589. // STG:
  590. //                token_action(curtok);
  591.                 curtok = lex_stream -> Gettoken(end_token);
  592.                 current_kind = lex_stream -> Kind(curtok);
  593.  
  594.                 continue;
  595.             }
  596.             //
  597.             // Since the null string is a valid Java program, this function
  598.             // will always succeed even if it has to delete the whole input.
  599.             //
  600.             else if (act == ACCEPT_ACTION)
  601.                  return;
  602.             else break; // loop around and keep trying until something is accepted.
  603.  
  604.             //
  605.             // Process a nonterminal
  606.             //
  607.             do
  608.             {
  609.                 state_stack_top -= (rhs[act] - 1);
  610.                 (this ->* rule_action[act])();
  611.                 act = nt_action(stack[state_stack_top], lhs[act]);
  612.             } while(act <= NUM_RULES);
  613.         } /* process_terminal */
  614.     }
  615.  
  616.     return;
  617. }
  618.  
  619.  
  620. //
  621. // This routine is invoked when an error is encountered in a "repair"
  622. // parser. It will place the parser back into a working configuration
  623. // by adjusting the state stack, the current token and the buffer.
  624. //
  625. void Parser::ErrorRepair(TokenObject error_token)
  626. {
  627.     SecondaryRepairInfo repair;
  628.  
  629.     repair.code = 0;
  630.     do
  631.     {
  632.         repair.distance = 0;
  633.         repair.num_deletions = state_stack_top + BUFF_UBOUND;
  634.  
  635.         buffer[1] = error_token;
  636.         buffer[0] = lex_stream -> Previous(buffer[1]);
  637.  
  638.         for (int k = 2; k < BUFF_SIZE; k++)
  639.             buffer[k] = lex_stream -> Next(buffer[k - 1]);
  640.  
  641.         int last_index;
  642.         for (last_index = MAX_DISTANCE - 1;
  643.              last_index >= 1 && lex_stream -> Kind(buffer[last_index]) == EOFT_SYMBOL;
  644.              last_index--);
  645.         last_index++;
  646.  
  647.         repair = ErrorSurgery(stack, state_stack_top, last_index, repair);
  648.         error_token = buffer[MAX_DISTANCE - MIN_DISTANCE + 2];
  649.     } while (repair.code == 0);
  650.  
  651. // STG:
  652. //    for (int i = repair.stack_position; i < state_stack_top; i++)
  653. //    {
  654. //        delete parse_stack[i];
  655. //    }
  656.  
  657.     state_stack_top = repair.stack_position;
  658.     lex_stream -> Reset(buffer[repair.buffer_position]);
  659.  
  660.     return;
  661. }
  662.  
  663.  
  664. //
  665. // Keep cutting "stuff" out around the error until a stable configuration
  666. // is found.
  667. //
  668. SecondaryRepairInfo Parser::ErrorSurgery
  669.          (int stck[], int stack_top,
  670.           int last_index, SecondaryRepairInfo repair)
  671. {
  672.     int stack_deletions = 0;
  673.     Location  previous_loc = Loc(buffer[2]);
  674.  
  675.     for (int top = stack_top; top >= 0 && repair.num_deletions >= stack_deletions; top--)
  676.     {
  677.         if (location_stack[top] < previous_loc)
  678.             stack_deletions++;
  679.         previous_loc = location_stack[top];
  680.  
  681.         for (int i = 1; i <= last_index && repair.num_deletions >= (stack_deletions + i - 1); i++)
  682.         {
  683.             int j = ParseCheck(stck, top, lex_stream -> Kind(buffer[i]), i + 1);
  684.  
  685.             if ((j - i + 1) > MIN_DISTANCE)
  686.             {
  687.                 int k = stack_deletions + i - 1;
  688.                 if ((k < repair.num_deletions) ||
  689.                     (j - k) > (repair.distance - repair.num_deletions))
  690.                 {
  691.                     repair.code = DELETION_CODE;
  692.                     repair.distance = j;
  693.                     repair.stack_position = top;
  694.                     repair.buffer_position = i;
  695.                     repair.num_deletions = k;
  696.                 }
  697.             }
  698.         }
  699.     }
  700.  
  701.     return repair;
  702. }
  703.  
  704.  
  705. /*****************************************************************/
  706. /* Try to parse until first_token and all tokens in BUFFER have  */
  707. /* been consumed, or an error is encountered. Return the number  */
  708. /* of tokens that were expended before the parse blocked.        */
  709. /*****************************************************************/
  710. int Parser::ParseCheck(int stck[], int stack_top, int first_token, int buffer_position)
  711. {
  712.     int max_pos,
  713.         indx,
  714.         ct,
  715.         act,
  716.         lhs_symbol;
  717.  
  718. /*****************************************************************/
  719. /* Initialize pointer for temp_stack and initialize maximum      */
  720. /* position of state stack that is still useful.                 */
  721. /*****************************************************************/
  722.     act = stck[stack_top];
  723.     if (first_token > NT_OFFSET)
  724.     {
  725.         temp_stack_top = stack_top;
  726.         max_pos = stack_top;
  727.         indx = buffer_position;
  728.         ct = lex_stream -> Kind(buffer[indx]);
  729.         lex_stream -> Reset(lex_stream -> Next(buffer[indx]));
  730.         lhs_symbol = first_token - NT_OFFSET;
  731.         act = nt_action(act, lhs_symbol);
  732.         if (act <= NUM_RULES)
  733.             goto process_non_terminal;
  734.     }
  735.     else
  736.     {
  737.         temp_stack_top = stack_top - 1;
  738.         max_pos = temp_stack_top;
  739.         indx = buffer_position - 1;
  740.         ct = first_token;
  741.         lex_stream -> Reset(buffer[buffer_position]);
  742.     }
  743.  
  744.     process_terminal: for (;;)
  745.     {
  746.         if (++temp_stack_top >= stack_length)  /* Stack overflow!!! */
  747.             return indx;
  748.         temp_stack[temp_stack_top] = act;
  749.  
  750.         act = t_action(act, ct, lex_stream);
  751.  
  752.         if (act <= NUM_RULES)                   /* reduce action */
  753.             temp_stack_top--;
  754.         else if (act < ACCEPT_ACTION ||          /* shift action */
  755.                  act > ERROR_ACTION)        /*shift-reduce action*/
  756.         {
  757.             if (indx == MAX_DISTANCE)
  758.                 return indx;
  759.             indx++;
  760.             ct = lex_stream -> Kind(buffer[indx]);
  761.             lex_stream -> Reset(lex_stream -> Next(buffer[indx]));
  762.             if (act > ERROR_ACTION)
  763.                  act -= ERROR_ACTION;
  764.             else goto process_terminal;
  765.         }
  766.         else if (act == ACCEPT_ACTION)           /* accept action */
  767.              return MAX_DISTANCE;
  768.         else return indx;                         /* error action */
  769.  
  770.         process_non_terminal:
  771.         do
  772.         {
  773.             temp_stack_top -= (rhs[act]-1);
  774.             lhs_symbol = lhs[act];
  775.             act = (temp_stack_top > max_pos
  776.                                   ? temp_stack[temp_stack_top]
  777.                                   : stck[temp_stack_top]);
  778.             act = nt_action(act, lhs_symbol);
  779.         } while(act <= NUM_RULES);
  780.  
  781.         max_pos = Min(max_pos, temp_stack_top);
  782.     } // process_terminal;
  783.  
  784.     return 0;
  785. }
  786.